package Thread_study.create;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/**
 * 学会线程的创建方式三：实现callable接口，结合FutureTask完成
 * 优点:
 *      线程任务类只是实现接口，可以继续继承类和实现接口，扩展性强
 *      而且可以在线程执行完毕后去获取线程执行的结果
 * 缺点：
 *      编码复杂一点
 */
public class ThreadDemo3 {
    public static void main(String[] args) {
        // 3.创建Callable任务对象
        Callable<String> call1 = new MyCallable(100);
        // 4.把Callable任务对象 交给FutureTask对象
        //  FutureTask对象的作用1：是Runnable的对象（实现类Runnable接口），可以交给Thread
        //  FutureTask对象的作用2：可以在线程执行完毕之后通过调用其get方法得到线程执行完毕的结果
        FutureTask<String> ft1 = new FutureTask<>(call1);
        //5.交给线程处理
        Thread thread1 = new Thread(ft1);
        // 6.启动线程
        thread1.start();

        Callable<String> call2 = new MyCallable(200);
        FutureTask<String> ft2 = new FutureTask<>(call2);
        Thread thread2 = new Thread(ft2);
        thread2.start();

        try {
            // 如果ft1任务没有执行完毕 这里的代码会等待，知道线程1跑完才提取结果
            String rs1 = ft1.get();
            System.out.println("第一个结果：" + rs1);
            // 如果ft2任务没有执行完毕 这里的代码会等待，知道线程2跑完才提取结果
            String rs2 = ft2.get();
            System.out.println("第二个结果：" + rs2);
        } catch (Exception e) {
            e.getStackTrace();
        }
    }
}

/**
 * 1.定义一个任务类 实现callable接口 应该声明线程任务执行完毕后的结果的数据类型
 */
class MyCallable implements Callable<String> {
    private int n;

    public MyCallable(int n) {
        this.n = n;
    }
    /*
        2.重写call方法（任务方法）
     */

    @Override
    public String call() throws Exception {
        int sum = 0;
        for (int i = 0; i <= n; i++) {
            sum += i;
        }
        return "子线程执行的结果是：" + sum;
    }
}
